/* parser.c
 * main entry point/driver for grammar parse
 * Note that the grammar is not allowed to perform any table access
 * since we need to be able to do basic parsing even while inside an
 * aborted transaction. therefore the data structures returned by the 
 * grammar are "raw" parsetree that still need to be analyzed by analyze.c
 * and related files.
 */
#include "primary_include_file.h"

#include "parser/gramparse.h"	/* required before parser/gram.h! */
#include "parser/gram.tab.h"
#include "parser/parser.h"

List *parsetree;  /* result of parsing is left here */
static bool have_lookahead;		/* is lookahead info valid? */
static int lookahead_token;	/* one-token lookahead */
static YYSTYPE lookahead_yylval;	/* yylval for lookahead token */
static YYLTYPE lookahead_yylloc;	/* yylloc for lookahead token */

/* raw_parser
 * Given a query in string form, do lexical and grammatical analysis.
 *
 * Return a list of raw (un-analyzed) parse trees.
 */
/* _line_43 */
List *
raw_parser(const char *str)
{
  int yyresult;

  parsetree = NULL;
  scanner_init(str);
  parser_init();

  yyresult = base_yyparse();
  
  scanner_finish();

  if (yyresult)
    return NIL;

  return parsetree;
}

/*
 * Intermediate filter between parser and base lexer (base_yylex in scan.l).
 *
 * The filter is needed because in some cases the standard SQL grammar
 * requires more than one token lookahead.	We reduce these cases to one-token
 * lookahead by combining tokens here, in order to keep the grammar LALR(1).
 *
 * Using a filter is simpler than trying to recognize multiword tokens
 * directly in scan.l, because we'd have to allow for comments between the
 * words.  Furthermore it's not clear how to do it without re-introducing
 * scanner backtrack, which would cost more performance than this filter
 * layer does.
 */
int filtered_base_yylex(void)
{
  int cur_token;
  /*
  int next_token;
  YYSTYPE cur_yylval;
  YYLTYPE cur_yylloc; */

  /* get next token --- we might already have it */
  if (have_lookahead){
    cur_token = lookahead_token;
    base_yylval = lookahead_yylval;
    base_yylloc = lookahead_yylloc;
    have_lookahead = false;
  } else
    cur_token = base_yylex();

  /* do we need to look ahead for possible multiword token ? */
  switch (cur_token)
  {  
  default: break;
  }
  
  return cur_token;
}
